#define SIMULATION1

using System;
using System.Collections.Generic;
using System.Text;
using HtmlParsingLibrary;
using System.IO;
using StockGeneral;
using System.Windows.Forms;
// Broker specific packages
//using StockBrokers;
using IciciDirect;
using TradingAlgos;
//using MoneyControlParser;

using System.Xml;
using System.Threading;
using System.Data.SqlClient;
using System.Security.Cryptography;
using HttpLibrary;
using System.Net;
using System.Diagnostics;
using System.Configuration;
using System.Globalization;
//using Miscellaneous;
using Charting;

namespace StockTrader
{
    partial class Program_old
    {                
        // Regular derivative order placement
        static void PlaceRegularDerivativeOrders(IBroker broker)
        {
            string traceString = null;
            string stockCode = "MYTECI";
            BrokerErrorCode errorCode = BrokerErrorCode.Success;
            // Place orders
            string orderRefNum;
            // Buy back the call
            //errorCode = broker.PlaceDerivativeOrder("UNITEC", 900, 1.85, OrderPriceType.LIMIT, OrderDirection.BUY,
            //    InstrumentType.OptionCallStock, new DateTime(2009, 1, 29), out orderRefNum);

            //traceString = "UNITEC-50-Jan-Call placed BUY order at 1.85: " + errorCode.ToString() + "\n";
            // Buy a future
            errorCode = broker.PlaceDerivativeOrder(stockCode, 900, 36, OrderPriceType.LIMIT, OrderDirection.BUY,
                InstrumentType.FutureStock, new DateTime(2009, 1, 29), OrderGoodNessType.IOC, out orderRefNum);

            traceString += "UNITEC-Jan-Future placed BUY order at 36: " + errorCode.ToString() + "\n";

            if (errorCode == BrokerErrorCode.Success)
            {
                // Place square-off oderer
                errorCode = broker.PlaceDerivativeOrder(stockCode, 900, 42, OrderPriceType.LIMIT, OrderDirection.SELL,
                    InstrumentType.FutureStock, new DateTime(2009, 1, 29), OrderGoodNessType.IOC, out orderRefNum);

                traceString += "UNITEC-Jan-Future placed SELL order at 42: " + errorCode.ToString() + "\n";

            }
            GeneralUtils.TraceOut(traceString);
        }
  
        // Regular order placement
        static void PlaceRegularEquityOrders(IBroker broker)
        {
            string traceString;
            string stockCode = "MUNISG";
            List<EquityOrderElement> ordersToPlace = new List<EquityOrderElement>();
            // Buy
            ordersToPlace.Add(new EquityOrderElement("MUNISG", 100, "5", OrderPriceType.LIMIT, OrderDirection.BUY, Exchange.NSE, EquityOrderType.DELIVERY, "0", "0"));
            // Sell
            ordersToPlace.Add(new EquityOrderElement("MUNISG", 100, "20", OrderPriceType.LIMIT, OrderDirection.SELL, Exchange.NSE, EquityOrderType.DELIVERY, "0", "0"));
            List<BrokerErrorCode> errorCodes = null;

            // Place orders
            errorCodes = broker.PlaceMultipleEquityOrders(ordersToPlace, 5);

            traceString = "Stock: " + stockCode + " :PlaceMultipleEquityOrders: 2\n";
            int o = 0;
            foreach (BrokerErrorCode errCodeEach in errorCodes)
            {
                EquityOrderElement order = ordersToPlace[o++];
                traceString += order.OrderDirection.ToString() + "-" + order.Quantity.ToString() + " of " + order.StockCode +
                    " at " + order.Price + ": " + errCodeEach.ToString() + "\n";
            }
            GeneralUtils.TraceOut(traceString);
        }

        static void Main(string[] args)
        {
            string traceString = null;

            Debug.Listeners.Add(new ConsoleTraceListener());


            // Testing arena before login

            traceString += "----------- Starting StockTrader ----------\n";
            if (GeneralUtils.IsMarketOpen())
            {
                traceString += "Market Open";
            }
            else
            {
                traceString += "Market Closed";
            }
            GeneralUtils.TraceOut(traceString);

            //ICICI Trader Start
            try
            {
                Thread.CurrentThread.Name = "Main Program";
                
                // Get configuration
                ProgramConfigParams config;
                if (!GeneralUtils.GetConfig(out config))
                {
                    return;
                }
                // Create ICICI broker account 
                IciciDirectBroker iciciDirectAccount = new IciciDirectBroker(config.username, config.password);

                // LOGIN 
                #region Login
                BrokerErrorCode errorCode = BrokerErrorCode.Success;
#if SIMULATION
#else
                errorCode = iciciDirectAccount.CheckAndLogInIfNeeded(true);
#endif
                // If login password is invalid then immediately exit the program 
                // to avoid locking of account by retrying with bad login/password
                if (errorCode == BrokerErrorCode.InvalidLoginPassword || errorCode == BrokerErrorCode.ChangePassword)
                {
                    GeneralUtils.TraceOut("InvalidLoginPassword");
                    return;
                }
                if (errorCode != BrokerErrorCode.Success)
                {
                    throw new Exception("CheckAndLogInIfNeeded(). BrokerErrorCode=" + errorCode.ToString());
                }

                List<BrokerAccountThread> brokerThreads = new List<BrokerAccountThread>();

                // Separate Login thread in background
                Thread thread = new Thread(new ParameterizedThreadStart(IciciUtils.Background_LoginWorkerThread));
                BrokerAccountObject iciciAccObj = new BrokerAccountObject(iciciDirectAccount);
                BrokerAccountThread iciciLoginThread = new BrokerAccountThread();
                iciciLoginThread.brokerAccountObj = iciciAccObj;
                iciciLoginThread.thread = thread;

                brokerThreads.Add(iciciLoginThread);

                iciciLoginThread.thread.Name = "Main Login Thread of \"" + config.username + "\"";
                iciciLoginThread.thread.IsBackground = true;
#if SIMULATION
#else                
                iciciLoginThread.thread.Start(iciciAccObj);
#endif
                #endregion 


                // Place regular orders
                //PlaceRegularEquityOrders(iciciDirectAccount);

                //PlaceRegularDerivativeOrders(iciciDirectAccount);

                // SET account-wide & stock-specific parameters
                #region AccountParams
                                                               
                // Calculate default stock-specific parameters

                double lossLimitStock = config.lossLimitAccount / config.numStocks;;
                double fundsStartingLimitStock = config.fundsStartingLimitAccount / config.numStocks;

                Exchange mainExchange = Exchange.BSE;
                double brokerageRate = IciciDirectBroker.brokerageRate;
                double minBrokerage = IciciDirectBroker.minBrokerage;

                #endregion

                // SETUP account & stock parameters and setup per-stock threads
                #region AccountAndStockThreadsSetup
                // Set account-wide funds limit and loss limit
                iciciDirectAccount.SetAccountParams(config.fundsStartingLimitAccount, config.lossLimitAccount);

                // Add stock symbols to trade today
                uint i = 0;

                List<StockThread> stockThreads = new List<StockThread>();
                for (i = 0; i < config.numStocks; i++)
                {
                    ProgramStockParams stockParams = config.stockParams[i];
                    EquityStockInformation stockInfo = iciciDirectAccount.AddStockInSystem(stockParams.stockCode);

                    // Set Stock-specific values
                    stockInfo.SetEquityStockParams(stockParams.stockCode, fundsStartingLimitStock, stockParams.stockAvailableStarting,
                        mainExchange, lossLimitStock, brokerageRate, minBrokerage);

                    StockThread stockThread = new StockThread();
                    // Create a new stock thread
                    Thread sThread = new Thread(new ParameterizedThreadStart(AlgoRunner.Background_StockWorkerThread));
                    // Params for the algo
                    Algo1_AlgoParams algoParams = new Algo1_AlgoParams(stockParams.stockTradingLot, stockParams.bCancelExistingOrdersAtStart, stockParams.bStartAFresh,
                        stockParams.bCancelOutstandingOrdersAtEnd, stockParams.initBidPrice, stockParams.initOfferPrice, false);
                    // Algo_Simple_Buy_Sell  
                    Algo1_SimplePairedBuySellDelivery algo = new Algo1_SimplePairedBuySellDelivery(iciciDirectAccount, stockInfo, algoParams);
                    // Make up the stockTrader object
                    StockAndBrokerObject stockTraderObj = new StockAndBrokerObject(iciciDirectAccount, stockInfo, algo);

                    stockThread.thread = sThread;
                    stockThread.stockAndBrokerObj = stockTraderObj;

                    stockThreads.Add(stockThread);

                    sThread.IsBackground = true;
                    sThread.Name = stockParams.stockCode;
                    sThread.Start(stockTraderObj);
                }


                #endregion

                // MKD_FutureTrader
                #region MKD_FutureTrader

                StockThread mkd_FutureTraderThread = new StockThread();
                if (config.bRunMKD_FutureTrader)
                {
                    // Params for the algo
                    ProgramMKDConfig mkdConfig;

                    if (GeneralUtils.GetConfigFor_MKD_FutureTrader(out mkdConfig))
                    {
                                                        
                        string[] stockParts = mkdConfig.stockCode.Split(';');
                        string[] qtyParts = mkdConfig.quantity.Split(';');

                        for (i = 0; i < stockParts.Length; i++)
                        {
                            string stockCode = stockParts[i];
                            int quantity = int.Parse(qtyParts[i]);
                            InstrumentType instrType = mkdConfig.instType;
                            //InstrumentType instrType = i == 0 ? InstrumentType.FutureIndex : InstrumentType.FutureStock;
                            //mkdConfig.instType;
                            //TickChart chart = new TickChart(stockCode);
                            // Separate Login thread in background
                            //Algo2_BuySellAnalyzer algo = new Algo2_BuySellAnalyzer(

                            //    null,//chart,
                            //    mkdConfig.mock,
                            //    mkdConfig.bIsReplayMode,
                            //    mkdConfig.replayTickFile,

                            //    mkdConfig.tickFileToAppend,

                            //    mkdConfig.useProbableTradeValue,

                            //    //mkdConfig.percChangeForMarketDirectionChange,
                            //    mkdConfig.percentageChangeForFreshBuy,
                            //    mkdConfig.percentageChangeForShortSquareOff,
                            //    mkdConfig.percentageChangeForFreshShort,
                            //    mkdConfig.percentageChangeForLongSquareOff,

                            //    mkdConfig.stopLossPerc, //stop loss percentage
                            //    mkdConfig.minProfitPerc, //minimum profit percentage

                            //    mkdConfig.brokerage,

                            //    mkdConfig.allowShort, //Short Sell Allowed
                            //    mkdConfig.allowLong, //Long Position Allowed

                            //    mkdConfig.longCeilingPrice,
                            //    mkdConfig.shortFloorPrice,

                            //    mkdConfig.initialOrder, //Initial Order

                            //    iciciDirectAccount,

                            //    stockCode,
                            //    quantity,
                            //    instrType,
                            //    mkdConfig.expiryDate
                            //    //mkdConfig.stockCode,
                            //    //mkdConfig.quantity,
                            //    //mkdConfig.instType,
                            //    //mkdConfig.expiryDate//,

                            //   // mkdConfig.maxTotalPositions,
                            //    //mkdConfig.maxLongPositions,
                            //    //mkdConfig.maxShortPositions
                            //    );


                            Algo3_MultipleLotBuySellAnalyzer algo = new Algo3_MultipleLotBuySellAnalyzer(

                                mkdConfig.mock,
                                mkdConfig.bIsReplayMode,
                                mkdConfig.replayTickFile,

                                mkdConfig.positionsFile,

                                mkdConfig.useProbableTradeValue,

                                mkdConfig.percChangeForMarketDirectionChange,
                                mkdConfig.percChangeThresholdForSquareOff,
                                //mkdConfig.percentageChangeForFreshBuy,
                                //mkdConfig.percentageChangeForShortSquareOff,
                                //mkdConfig.percentageChangeForFreshShort,
                                //mkdConfig.percentageChangeForLongSquareOff,

                                mkdConfig.stopLossPerc, //stop loss percentage
                                mkdConfig.minProfitPerc, //minimum profit percentage


                                mkdConfig.allowShort, //Short Sell Allowed
                                mkdConfig.allowLong, //Long Position Allowed

                                null,  // pending open positions or inital orders

                                iciciDirectAccount,
                                stockCode,
                                quantity,
                                instrType,
                                mkdConfig.expiryDate,
                                //mkdConfig.stockCode,
                                //mkdConfig.quantity,
                                //mkdConfig.instType,
                                //mkdConfig.expiryDate//,

                                mkdConfig.maxTotalPositions,
                                mkdConfig.maxLongPositions,
                                mkdConfig.maxShortPositions,
                                                                
                                mkdConfig.longCeilingPrice,
                                mkdConfig.shortFloorPrice,
                                mkdConfig.positionSpacingPerc,
                                mkdConfig.brokerage

                            );

                            EquityStockInformation stockInfo = new EquityStockInformation(stockCode);
                            // Make up the stockTrader object
                            StockAndBrokerObject stockTraderObj = new StockAndBrokerObject(iciciDirectAccount, stockInfo, algo);

                            thread = new Thread(new ParameterizedThreadStart(AlgoRunner.Background_StockWorkerThread));
                            mkd_FutureTraderThread.stockAndBrokerObj = stockTraderObj;
                            mkd_FutureTraderThread.thread = thread;

                            stockThreads.Add(mkd_FutureTraderThread);

                            mkd_FutureTraderThread.thread.Name = "MKD_FutureTrader_" + stockCode;
                            mkd_FutureTraderThread.thread.IsBackground = true;
                            mkd_FutureTraderThread.thread.Start(stockTraderObj);
                        }
                    }
                }

                #endregion

                GeneralUtils.CheckProgramExit(stockThreads, brokerThreads, config);
            }
            catch(Exception e)
            {
                // or use e.Message only for summary description
                GeneralUtils.TraceOut("Exception: " + e.ToString());
            }

            traceString = "----------- Ending StockTrader ----------\n";
            GeneralUtils.TraceOut(traceString);

            if (GeneralUtils.IsSendSystemInHibernation())
            {
                bool retVal = Application.SetSuspendState(PowerState.Hibernate, false, false);

                if (retVal == false)
                {
                    GeneralUtils.TraceOut("Could not hybernate the system.");
                }
                else
                {
                    GeneralUtils.TraceOut("System sent to hibernation");
                }
            }
            //Console.ReadLine();
        }

    }
}
